import 'dart:io';

import 'package:archive/archive.dart';
import 'package:flutter/services.dart';
import 'package:get/get.dart';
import 'package:flutter_easyloading/flutter_easyloading.dart';
import 'package:flutter_blue_plus/flutter_blue_plus.dart';
import 'package:mcumgr_flutter/mcumgr_flutter.dart';
import 'dart:typed_data';
import 'dart:convert';
import 'dart:async';
import 'package:dio/dio.dart'; // Add this import
import 'package:path_provider/path_provider.dart';

import 'package:signage/app/modules/device/models/device_cached_info.dart';
import 'package:signage/app/services/bluetooth_service.dart';
import 'package:signage/l10n/l10n.dart';
import 'package:signage/widgets/edit_dialog.dart';
import 'package:wakelock_plus/wakelock_plus.dart';
import 'package:signage/app/utils/http_client.dart';

class OtaController extends FullLifeCycleController with FullLifeCycleMixin {
  final BluetoothManager bluetoothManager = Get.find<BluetoothManager>();

  // OTA相关的UUID常量
  static const String OTA_SERVICE_UUID = "1530";
  static const String OTA_CONTROL_UUID = "1531";
  static const String OTA_DATA_UUID = "1532";

  // 设备信息服务UUID
  static const String DEVICE_INFO_SERVICE_UUID = "180A";
  static const String FIRMWARE_VERSION_UUID = "2A26";

  // 状态跟踪
  final deviceConnectionStates = <String, bool>{}.obs;
  final isConnectingDevice = false.obs;

  // 新增 DFU 相关属性
  final dfuRunning = false.obs;

  final version = '1.2.0'.obs;

  final Dio _dio = Dio();

  final updateStatusList = <DfuUpdate>[].obs;

  final HttpClient httpClient = HttpClient();

  @override
  void onInit() async {
    super.onInit();
    WakelockPlus.enable();
    // 连接到设备
    _firmwareUpdateManager = FirmwareUpdateManagerFactory();
    final boardList = <String>[];
    bluetoothManager.deviceInfoMap.values.forEach((device) {
      print('device: ${device.board}');
      if (device.board != null && !boardList.contains(device.board)) {
        boardList.add(device.board ?? '');
      }
    });
    print('boardList: $boardList');

    await checkUpdate(boardList);

    // devicesNeedUpdate.value = bluetoothManager.deviceInfoMap.values
    //     .where(
    //         (device) => isNewVersionAvailable(device.firmwareVersion, "1.2.w"))
    //     .toList();

    // updateStatusList.value = devicesNeedUpdate
    //     .map((device) => DfuUpdate(
    //           progress: 0.0.obs,
    //           filePath: device.filePath ?? '',
    //           board: device.board ?? '',
    //           deviceAddress: device.id,
    //           version: '12.2',
    //           status: DfuUpdateStatus.ready.obs,
    //         ))
    //     .toList();
  }

  @override
  void onReady() {
    super.onReady();
    print('🚀 OTA Controller is ready');
  }

  @override
  void onClose() {
    super.onClose();
  }

  // 生命周期方法保持不变
  @override
  void onDetached() => print('🔌 App detached');
  @override
  void onInactive() => print('💤 App inactive');
  @override
  void onPaused() => print('⏸️ App paused');
  @override
  void onResumed() => print('📱 App resumed');
  @override
  void onHidden() => print('🙈 App hidden');

  // 获取设备连接状态
  Stream<BluetoothConnectionState> getDeviceConnectionState(String deviceId) {
    try {
      final device = FlutterBluePlus.connectedDevices
          .firstWhere((d) => d.remoteId.toString() == deviceId);
      return device.connectionState;
    } catch (e) {
      return Stream.value(BluetoothConnectionState.disconnected);
    }
  }

  // 获取设备缓存信息
  DeviceCachedInfo? getDeviceCachedInfo(String deviceId) {
    return bluetoothManager.deviceInfoMap[deviceId];
  }

  // OTA升级相关方法
  Future<void> checkUpdate(List<String> boardList) async {
    try {
      EasyLoading.show(
        status: AppLocalizations.of(Get.context!)!.translate('checking_updates')
      );
      // TODO: 从服务器获取最新固件信息
      final latestFirmwarelist = await _fetchLatestFirmware(boardList);

      devicesNeedUpdate.value =
          bluetoothManager.deviceInfoMap.values.where((device) {
        final latestFirmware = latestFirmwarelist
            .firstWhereOrNull((firmware) => firmware.board == device.board);
       if (latestFirmware == null) return false;
        device.filePath = latestFirmware.path;
        device.updateVersion = latestFirmware.version;
        return isNewVersionAvailable(
            device.firmwareVersion, latestFirmware.version);
      }).toList();

      updateStatusList.value = devicesNeedUpdate
          .map((device) => DfuUpdate(
                progress: 0.0.obs,
                deviceAddress: device.id,
                board: device.board ?? '',
                status: DfuUpdateStatus.ready.obs,
                filePath: device.filePath ?? '',
                version: device.updateVersion ?? '',
              ))
          .toList();
    } catch (e) {
      printError(info: 'Error checking update: $e');
      EasyLoading.showError(
        AppLocalizations.of(Get.context!)!.translate('update_check_failed')
            .replaceFirst('{error}', e.toString())
      );
    } finally {
      EasyLoading.dismiss();
    }
  }

  final devicesNeedUpdate = <DeviceCachedInfo>[].obs;

  bool isNewVersionAvailable(String currentVersion, String newVersion) {
    print('currentVersion: $currentVersion, newVersion: $newVersion');
    // Split versions into components
    List<String> currentParts = currentVersion.split('.');
    List<String> newParts = newVersion.split('.');

    // Ensure we have at least 3 components by padding with zeros
    while (currentParts.length < 3) currentParts.add('0');
    while (newParts.length < 3) newParts.add('0');

    // Compare each component
    for (int i = 0; i < 3; i++) {
      int currentNum = int.tryParse(currentParts[i]) ?? 0;
      int newNum = int.tryParse(newParts[i]) ?? 0;

      if (newNum > currentNum) {
        return true; // New version is higher
      } else if (newNum < currentNum) {
        return false; // Current version is higher
      }
      // If equal, continue to next component
    }

    return false; // Versions are the same
    // return true;
  }

  late FirmwareUpdateManagerFactory _firmwareUpdateManager;

  Future<void> startOtaUpdate(DfuUpdate deviceInfo) async {
    try {
      if (deviceInfo.status.value == DfuUpdateStatus.updating) {
        Get.dialog(TipsDialog(
          title: AppLocalizations.of(Get.context!)!.translate('tip'),
          text: AppLocalizations.of(Get.context!)!.translate('cancel_update_confirm'),
          onConfirm: () {
            Get.back();
            cancelUpdate(deviceInfo);
          },
        ));
        return;
      }

      if (deviceInfo.status.value == DfuUpdateStatus.completed) {
        return;
      }

      deviceInfo.status.value = DfuUpdateStatus.updating;
      devicesNeedUpdate.refresh();
      
      final firmwarePath = await _downloadFirmware(
          deviceInfo.board, deviceInfo.filePath, deviceInfo.version);
      
      final updateManager = await _firmwareUpdateManager
          .getUpdateManager(deviceInfo.deviceAddress);
      
      // 保存updateManager实例以便后续取消操作
      deviceInfo.updateManager = updateManager;
      
      final updateStream = updateManager.setup();

      updateStream.listen((event) {
        if (event == FirmwareUpgradeState.success ||
            event == FirmwareUpgradeState.confirm) {
          _handleUpdateSuccess(deviceInfo);
        } else {
          print(event);
        }
      });

      updateManager.logger.logMessageStream
          .where((log) => log.level.rawValue > 1)
          .listen((log) {
        print("Device ${deviceInfo.deviceAddress}: ${log.message}");
      });

      // 为每个设备单独处理进度
      updateManager.progressStream.listen((event) {
        print("Device ${deviceInfo.deviceAddress}: ${event.bytesSent} / ${event.imageSize} bytes sent");
        deviceInfo.progress.value = event.bytesSent / event.imageSize;
        updateStatusList.refresh(); // 刷新整个列表以更新UI
      });

      final imageData = File(firmwarePath);
      await updateManager.updateWithImageData(
          imageData: imageData.readAsBytesSync());
    } catch (e) {
      printError(info: 'Error during OTA update: $e');
      EasyLoading.showError(
        AppLocalizations.of(Get.context!)!.translate('update_failed')
            .replaceFirst('{error}', e.toString())
      );
      await cancelUpdate(deviceInfo);
    }
  }

  void _handleUpdateSuccess(DfuUpdate deviceInfo) {
    print("Update Success ${deviceInfo.version} for device ${deviceInfo.deviceAddress}");
    deviceInfo.status.value = DfuUpdateStatus.completed;
    
    // 更新设备信息并持久化
    final device = bluetoothManager.deviceInfoMap[deviceInfo.deviceAddress];
    if (device != null) {
      device.firmwareVersion = deviceInfo.version;
      bluetoothManager.deviceInfoMap.refresh();
      bluetoothManager.saveDevicesToStorage();
      
      // 更新需要更新的设备列表
      final index = devicesNeedUpdate.indexWhere((d) => d.id == deviceInfo.deviceAddress);
      if (index != -1) {
        devicesNeedUpdate[index].firmwareVersion = deviceInfo.version;
        devicesNeedUpdate.refresh();
      }
    }
    
    // 从更新列表中移除已完成的设备
    updateStatusList.removeWhere((d) => d.deviceAddress == deviceInfo.deviceAddress);
    updateStatusList.refresh();
  }

  Future<String> _downloadFirmware(
      String board, String filename, String updateVersion) async {
    try {
      final tempDir = await getTemporaryDirectory();
      final tempPath = '${tempDir.path}/${board}/${updateVersion}/$filename';

      if (File('${tempDir.path}/${board}/$updateVersion/app_update.bin')
          .existsSync()) {
        return '${tempDir.path}/${board}/$updateVersion/app_update.bin';
      }

      // Prepare authentication
      final username = '2B0E3BFF7AEFEF5D35CBCD8A9DE44EAA';
      final password = '9E3F8B5B460F87E200C0B4A58D47E40B';

      // Create Dio instance with authentication
      final dioDownload = Dio();
      dioDownload.options.headers['Authorization'] =
          'Basic ${base64Encode(utf8.encode('$username:$password'))}';

      // Get temporary directory for download
      print(
          'download firmware  : ${'http://192.144.167.95:10001/download/${board}/$filename'}');
      // Download firmware
      await dioDownload.download(
        filename,
        tempPath,
        onReceiveProgress: (received, total) {},
      );

      await extractZip(tempPath, '${tempDir.path}/${board}/$updateVersion');

      return '${tempDir.path}/${board}/app_update.bin';
    } catch (e) {
      printError(info: 'Firmware download error: $e');
      throw Exception('Failed to download firmware: $e');
    }
  }

  Future<void> extractZip(String zipFilePath, String destinationPath) async {
    // 读取 ZIP 文件
    final bytes = File(zipFilePath).readAsBytesSync();
    final archive = ZipDecoder().decodeBytes(bytes);

    // 解压到目标路径
    for (final file in archive) {
      final filename = file.name;
      final outputFilePath = '$destinationPath/$filename';

      if (file.isFile) {
        // 创建文件夹
        final outputFile = File(outputFilePath);
        await outputFile.parent.create(recursive: true);
        // 写入文件
        await outputFile.writeAsBytes(file.content as List<int>);
      } else {
        // 创建目录
        await Directory(outputFilePath).create(recursive: true);
      }
    }
  }

  Future<void> cancelUpdate(DfuUpdate deviceInfo) async {
    if (deviceInfo.status.value == DfuUpdateStatus.updating) {
      deviceInfo.status.value = DfuUpdateStatus.ready;
      devicesNeedUpdate.refresh();
    }
    final updateManager =
        await _firmwareUpdateManager.getUpdateManager(deviceInfo.deviceAddress);
    updateManager.cancel();
    updateManager.kill();
  }

  // 辅助方法
  Future<List<FirmwarePackage>> _fetchLatestFirmware(
      List<String> boardList) async {
    List<FirmwarePackage> firmwareList = [];
    // Replace with your actual server URL
    for (var board in boardList) {
      // final response = await _dio.post(
      //   'http://192.144.167.95:10001/query',
      //   options: Options(
      //     contentType: Headers.jsonContentType,
      //   ),
      //   data: {"board": '${board}', "filename": "dfu_application.zip"},
      // );
      final response = await httpClient.getBluetoothFirmware(board);
      if (response.code == 200) {
        final firmwareData = response.firmware;

        // Validate the response structure
        if (firmwareData == null) {
          throw Exception('No firmware data received');
        }

        // Construct FirmwarePackage
        final firmwarePackage = FirmwarePackage(
          version: firmwareData.version ?? 'unknown',
          board: board,
          data: Uint8List(
              0), // You might want to download the actual firmware data
          path: firmwareData.url ??
              '', // You'll need to download and save the firmware file
        );
        firmwareList.add(firmwarePackage);
      }
    }
    print('firmwareList: $firmwareList');
    return firmwareList;
  }

  @override
  void dispose() {
    WakelockPlus.disable();
    super.dispose();
  }

  void updateAllDevices() {
    for (var device in updateStatusList) {
      startOtaUpdate(device);
    }
  }
}

// 固件包模型
class FirmwarePackage {
  final String version;
  final String board;
  final Uint8List data;
  final String path;

  FirmwarePackage({
    required this.version,
    required this.board,
    required this.data,
    required this.path,
  });
}

enum DfuUpdateStatus {
  ready,
  updating,
  completed,
}

// 在文件底部添加此类
class DfuUpdate {
  final RxDouble progress;
  final String deviceAddress;
  final Rx<DfuUpdateStatus> status;
  final String board;
  final String filePath;
  final String version;
  FirmwareUpdateManager? updateManager; // 新增：保存updateManager实例

  DfuUpdate({
    required this.progress,
    required this.deviceAddress,
    required this.status,
    required this.board,
    required this.filePath,
    required this.version,
    this.updateManager,
  });
}
